
_ = require 'underscore'
fsp = require '../bin/libs/fs-promises'
Q = require 'q'
path = require 'path'
user = require '../db/User'
crypto = require 'crypto'
captchapng = require 'captchapng'
sendMail = require '../bin/libs/mail'

module.exports= (app)->

  ITERATOR_COUNT = 1024 #迭代循环1024次
  PASSWORD_LENGTH = 32  #密码的位数
  SALT_LENGTH = 8 #盐值位数
  SALT_COOKIE = "remember_me&&!!" #cookie验证

  #生成密文，默认HMAC函数是sha1算法
  _encrypt = (txt, salt, cb) ->
    txt = txt || ""
    txt = txt.toString()
    crypto.randomBytes SALT_LENGTH, (err, result) ->
      cb err if err
      salt = salt || result.toString('hex')
      crypto.pbkdf2 txt, salt, ITERATOR_COUNT, PASSWORD_LENGTH, (err, hash) ->
        cb err, hash.toString('hex'), salt

  #生成密文，默认HMAC函数是sha1算法
  _signedCookies = (txt, salt, cb) ->
    txt = txt || ""
    txt = txt.toString()
    crypto.pbkdf2 txt, salt, 1024, 8, (err, hash) ->
      cb err, hash.toString('hex'), salt


  # 用户注册－－填写信息页面
  app.get '/login', (req, res, next) ->
    # noLogin 头部显示用户信息判断
    return res.redirect '/' if req.session and req.session.user and req.session.user.role == "user"
    res.render 'login', {layout: false,  showTitle: "我是登录页面", noLogin: true}

  # #签名Cookies
  # app.get '/signCookies', (req, res, next) ->
  #   _signedCookies "ww", SALT_COOKIE, (err, hash) ->
  #     res.cookie("remember_me", JSON.stringify({name: "ww", sign: hash}))
  #     res.send "Cookies－remember_me 签名"

  #推出登录
  app.get '/logout', (req, res, next) ->
    req.session.user = null
    res.redirect '/login'


  #用户登录
  app.post '/login', (req, res, next) ->
    user_data = _.pick(req.body, ['username', 'password'])
    # 必须保证密码不能为空
    user_data.password = user_data.password || ""
    new Promise (resolve, reject) ->
      user.findOne {username: user_data.username, role: "user"}, (err, data) ->
        return reject('登录失败') if err
        return reject('用户名不存在') if !data
        resolve(data)
    .then (data) ->
      new Promise (resolve, reject) ->
        _encrypt user_data.password, data.salt, (err, hash, salt) ->
          return reject('登录失败') if err
          return reject('密码错误') if hash != data.password
          resolve(data)
    .then (data) ->
      user_json =  _.pick(data, ['username', 'role', 'photo'])
      req.session.user = user_json
      # res.redirect '/'
      res.status(200).json {code: 0, message:"登录成功", data: user_json}
    .catch (err) ->
      res.status(200).json {code:-1, message: err}


  #注册用户
  app.post '/register', (req, res, next) ->
    user_data = _.pick(req.body, ['username', 'password', 'photo'])
    # 必须保证密码不能为空
    user_data.password = user_data.password || ""
    new Promise (resolve, reject) ->
      user.findOne username: user_data.username, (err, data) ->
        return reject('注册失败 系统异常') if err
        return reject('用户名已存在') if data
        resolve()
    .then () ->
      new Promise (resolve, reject) ->
        _encrypt user_data.password, '', (err, hash, salt) ->
          return reject('注册失败 系统异常') if err
          resolve "#{hash};#{salt}"
    .then (str) ->
      #这样做因为resolve()只能返回一个参数
      user_data.password = str.split(";")[0]
      user_data.salt = str.split(";")[1]
      new Promise (resolve, reject) ->
        user.save user_data, (err, data) ->
          return reject('注册失败 系统异常') if err
          resolve(data)
    .then (data) ->
      res.status(200).json {code: 0, message:"注册成功"}
    .catch (err) ->
      res.status(200).json {code:-1, message: err}

  #查询所有用户
  app.get '/users', (req, res, next) ->
    user.findAll (err, data) ->
       return res.status(404).json {code:-1, message:'Can\'t find users.'} if err
       res.status(200).json {code: 0, data: data}

  #分页查询用户
  app.get '/users/:page/:limit', (req, res, next) ->
    page = req.params.page
    limit = req.params.limit
    keyword = req.query.keyword || ""
    user.list page, limit, keyword, (err, data) ->
       return res.status(404).json {code:-1, message:'Can\'t find users.'} if err
       res.status(200).json {code: 0, data: data}

  #查询用户 by id
  app.get '/users/:user_id', (req, res, next) ->
    user.findOne _id: req.params.user_id, (err, data) ->
       return res.status(404).json {code:-1, message:'Can\'t find users.'} if err
       obj =  _.pick(data, ['username', 'role', 'photo'])
       res.status(200).json {code: 0, data: obj}

  #删除用户 by id
  app.delete '/users/:user_id', (req, res, next) ->
    new Promise (resolve, reject) ->
      resolve()
    .then () ->
      new Promise (resolve, reject) ->
        user.findOneAndRemove _id: req.params.user_id, (err, obj) ->
          return reject(err) if err
          resolve(obj)
    .then (data) ->
      res.status(200).json {code: 0, data: 'delete successfully'}
    .catch (err) ->
      console.log err
      res.status(404).json {code:-1, message:'delete Failed'}

  #更新用户 by id
  app.put '/users/:user_id', (req, res, next) ->
    update =  _.pick(req.body, ['username', 'password', 'role'])
    user.findOneAndUpdate _id: req.params.user_id, update, (err, data) ->
       return res.status(404).json {code:-1, message:'Can\'t find users.'} if err
       res.status(200).json {code: 0, data: 'update successfully'}



  ##
  # 密码相关
  ##

  app.get '/resetpwd', (req, res, next) ->
    res.render 'apps/reset-password', {layout: false,  showTitle: "", noLogin: true}


  #图形验证码
  app.get '/validateCode', (req, res, next) ->
    code = parseInt(Math.random()*9000+1000)
    req.session.validateCode = code
    p = new captchapng(80,30, code);
    p.color(0, 0, 0, 0);
    p.color(80, 80, 80, 255);
    img = p.getBase64();
    imgbase64 = new Buffer(img,'base64');
    res.writeHead(200, {
          'Content-Type': 'image/png'
      });
    res.end(imgbase64);


  #发送邮件验证码 验证图形验证码是否正确
  app.post '/sendEmailCode', (req, res, next) ->
    new Promise (resolve, reject) ->
      user.findOne email: req.body.username, (err, data) ->
        return reject('系统异常') if err
        return reject('邮箱不存在') if !data
        resolve()
    .then () ->
      new Promise (resolve, reject) ->
        if +req.body.vcode == +req.session.validateCode then resolve() else reject('验证码错误')
    .then ->
      emailCode = parseInt(Math.random()*9000+1000)
      req.session.emailCode = emailCode
      content = '重置密码的验证码是：' + emailCode
      subject = '找回密码'
      obj = {email: req.body.username, content:content,subject:subject}
      sendMail obj
    .then (msg) ->
      res.status(200).json {code: 0, message: 'send successfully'}
    .catch (err) ->
      res.status(200).json {code:-1, message: err}

  #验证用户各种验证码 1: 通过 0: 图形验证码错误 -1: 邮箱验证码错误
  app.post '/validateEmailCode', (req, res, next) ->
    new Promise (resolve, reject) ->
      user.findOne email: req.body.username, (err, data) ->
        return reject('系统异常') if err
        return reject('邮箱不存在') if !data
        resolve()
    .then () ->
      new Promise (resolve, reject) ->
        if +req.body.vcode == +req.session.validateCode then resolve() else reject('图形验证码错误')
    .then ->
      new Promise (resolve, reject) ->
        if +req.body.ecode == +req.session.emailCode then resolve() else reject('邮箱验证码错误')
    .then (msg) ->
      req.session.isRetPwd = true;
      req.session.email = req.body.username;
      res.status(200).json {code: 0, message: 'successfully'}
      # res.redirect '/updatePassword'
    .catch (err) ->
      res.status(200).json {code:-1, message: err}

  #验证合法信息后 允许更新密码
  app.get '/updatePassword', (req, res) ->
    return res.redirect '/resetpwd' if !req.session.isRetPwd
    res.render 'apps/updatePassword', {layout: false,  showTitle: "", noLogin: true}

  #更新密码
  app.post '/updatePassword', (req, res) ->
    return res.status(200).json {code:-1, message: '不合法用户'} if !req.session.isRetPwd ||  !req.session.email
    email = req.session.email
    new Promise (resolve, reject) ->
      _encrypt req.body.password, '', (err, hash, salt) ->
        return reject('系统异常') if err
        resolve "#{hash};#{salt}"
    .then (str) ->
      #这样做因为resolve()只能返回一个参数
      user_data = {password: str.split(";")[0], salt: str.split(";")[1]}
      console.log user_data
      new Promise (resolve, reject) ->
        user.findOneAndUpdate email: email, user_data, (err, data) ->
          return reject('更新失败') if err || !data
          resolve(data)
    .then (msg) ->
      #需要重新邮箱验证
      req.session.isRetPwd  = false;
      req.session.email = '';
      res.status(200).json {code: 0, message: 'update successfully'}
    .catch (err) ->
      res.status(200).json {code:-1, message: err}
